package com.gable.report.service.impl;


import com.gable.report.dao.IChartsAreaSearchDao;
import com.gable.report.dao.IChartsForAreaAllocationDao;
import com.gable.report.model.*;
import com.gable.report.service.ChartsForAreaAllocationService;
import com.gable.report.thread.RedisListStoreThread;
import com.gable.report.thread.RedisValueStoreThread;
import com.gable.report.util.ChartsUtil;
import com.gable.report.util.RedisUtil;
import com.gable.report.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.gable.report.util.ChartsUtil.*;
import static com.gable.report.util.RedisUtil.getAreaModuleKey;
import static com.gable.report.util.RedisUtil.getListValue;

/**
 * Created by lvdouStart on 2017/7/19.
 * 区报表基本数据service实现类
 */
@Service
public class ChartsForAreaAllocationServiceImpl implements ChartsForAreaAllocationService {

    private final Log logger = LogFactory.getLog(this.getClass());

    @Autowired
    IChartsForAreaAllocationDao chartsForAreaAllocationDao;

    @Autowired
    IChartsAreaSearchDao chartsAreaSearchDao;


    private RedisTemplate redisTemplate;

    @Autowired(required = false)
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        //设置redis数据库
        //JedisConnectionFactory jedisConnectionFactory = (JedisConnectionFactory)redisTemplate.getConnectionFactory();
        //jedisConnectionFactory.setDatabase(2);
        this.redisTemplate = redisTemplate;
    }

    @Override
    public Map<String, Object> queryAllAssetsForHospitalIndex(User user, ChartsAreaQuery chartsAreaQuery) throws Exception {
        Map<String,Object> paramMap = getParamMap(user, chartsAreaQuery);
        Map<String,Object> returnMap = new HashMap<>();
        //总资产数据
        ChartsBaseDataView allAssets = getAllAssets(user,paramMap,chartsAreaQuery);
        //医院等级饼状图
        List<Map<String, Object>> hospitalLevelList;
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)) {
            //医院key
            String key = getAreaModuleKey("allocation",user,"hospitalLevel",chartsAreaQuery);
            hospitalLevelList = RedisUtil.getListValue(redisTemplate, key);
            if (hospitalLevelList == null) {
                //医院等级饼状图数据
                hospitalLevelList = chartsForAreaAllocationDao.queryHospitalLevels(paramMap);
                // 把数据存入缓存
                new Thread(new RedisListStoreThread(redisTemplate, key, hospitalLevelList)).start();
            }
        }else{
            hospitalLevelList = chartsForAreaAllocationDao.queryHospitalLevels(paramMap);
        }
        //一级68分类饼状图
        List<Map<String, Object>> deviceFirstTypeList;
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)) {
            //医院key
            String key = getAreaModuleKey("allocation",user,"firstType",chartsAreaQuery);
            deviceFirstTypeList = RedisUtil.getListValue(redisTemplate, key);
            if (deviceFirstTypeList == null) {
                //一级68分类饼状图数据
                deviceFirstTypeList = chartsForAreaAllocationDao.queryFirstDeviceTypes(paramMap);
                // 把数据存入缓存
                new Thread(new RedisListStoreThread(redisTemplate, key, deviceFirstTypeList)).start();
            }
        }else{
            deviceFirstTypeList = chartsForAreaAllocationDao.queryFirstDeviceTypes(paramMap);
        }
        returnMap.put("hospitalLevel",hospitalLevelList);
        returnMap.put("allAssets",allAssets);
        returnMap.put("firstTypeList",deviceFirstTypeList);
        return returnMap;
    }

    @Override
    public Map<String, Object> queryAllAssetsForDeviceIndex(User user, ChartsAreaQuery chartsAreaQuery) throws Exception {
        Map<String,Object> returnMap = new HashMap<>();
        Map<String,Object> paramMap = getParamMap(user, chartsAreaQuery);
        ChartsBaseDataView allAssets = getAllAssets(user,paramMap,chartsAreaQuery);
        //查询该区的设备金额区间
        Map<String,Object> priceParamMap = new HashMap<>();
        priceParamMap.put("regionCode",userRegionMap.get(user.getId()));
        priceParamMap.put("type",1);
        ChartsPriceCategory chartsPriceCategory = chartsAreaSearchDao.queryPriceCategory(priceParamMap);
        if(chartsPriceCategory == null){
            priceParamMap.put("regionCode",310112);
            chartsPriceCategory = chartsAreaSearchDao.queryPriceCategory(priceParamMap);
        }
        Map<String,Object> priceCategoryNameMap = ChartsUtil.getDevicePriceCategoryName(chartsPriceCategory);
        //组装金额区间
        paramMap.put("asName",priceCategoryNameMap.get("asName"));
        List<ChartsBaseDataView> list;
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)) {
            //医院key
            String key = getAreaModuleKey("allocation",user,"priceCategory",chartsAreaQuery);
            list = RedisUtil.getListValue(redisTemplate, key);
            if (list == null) {
                //金额区间数据
                list = chartsForAreaAllocationDao.queryDevicePriceCategory(paramMap);
                // 把数据存入缓存
                new Thread(new RedisListStoreThread(redisTemplate, key, list)).start();
            }
        }else{
            list = chartsForAreaAllocationDao.queryDevicePriceCategory(paramMap);
        }
        List<ChartsBaseDataView> PriceCategoryList = new ArrayList();//返回的金额区间情况
        //查询结果可能发生缺少的情况 通过下面方法补全
        List<String> priceCategoryList = (List<String>)priceCategoryNameMap.get("priceCategory");
        for(String str : priceCategoryList){
            ChartsBaseDataView cbv = null;
            for(ChartsBaseDataView obj : list){
                if(obj != null && obj.getName() != null && str.equals(obj.getName())){
                    cbv = obj;
                }
            }
            if(cbv == null){
                cbv = new ChartsBaseDataView();
                cbv.setName(str);
            }
            PriceCategoryList.add((ChartsBaseDataView)handleNull(cbv));
        }
        returnMap.put("allAssets",allAssets);
        returnMap.put("amountList",PriceCategoryList);
        return returnMap;
    }

    @Override
    public Map<String, Object> queryAllAssetsForDeviceAgeLimit(User user, ChartsAreaQuery chartsAreaQuery) throws Exception {
        Map<String,Object> returnMap = new HashMap<>();
        Map<String,Object> paramMap = getParamMap(user, chartsAreaQuery);
        ChartsBaseDataView allAssets = getAllAssets(user,paramMap,chartsAreaQuery);
        Map<String,Object>  ageLimitCategoryMap = ChartsUtil.getAgeLimitCategoryName(null); //返回的年限指数区间情况
        //组装年限指数区间
        paramMap.put("asNameCur",ageLimitCategoryMap.get("asNameCur"));
        paramMap.put("asNameLast",ageLimitCategoryMap.get("asNameLast"));
        List<ChartsBaseDataView> list;
        //redis未宕机且只有年份和设备类型筛选的情况
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)){
            //查询redis中是否有该缓存
            String key = getAreaModuleKey("allocation",user,"ageLimit",chartsAreaQuery);
            list = getListValue(redisTemplate,key);
            if(list == null){
                //年限指数区间数据
                list = chartsForAreaAllocationDao.queryDeviceAgeLimitCategory(paramMap);
                new Thread(new RedisListStoreThread(redisTemplate,key,list)).start();
            }
        }else{
            list = chartsForAreaAllocationDao.queryDeviceAgeLimitCategory(paramMap);
        }

        List<ChartsBaseDataView> ageLimitCategoryList = new ArrayList();//返回的年限指数区间情况
        //查询结果可能发生缺少的情况 通过下面方法补全
        List<String> ageLimitCategoryNameList = (List<String>)ageLimitCategoryMap.get("ageLimitCategory");
        for(String str : ageLimitCategoryNameList){
            ChartsBaseDataView cbv = null;
            for(ChartsBaseDataView chartsBaseDataView : list){
                if(chartsBaseDataView != null && chartsBaseDataView.getName() != null && str.equals(chartsBaseDataView.getName())){
                    cbv = chartsBaseDataView;
                }
            }
            if(cbv == null){
                cbv = new ChartsBaseDataView();
                cbv.setName(str);
            }
            ageLimitCategoryList.add(cbv);
        }
        returnMap.put("allAssets",allAssets);
        returnMap.put("ageLimitList",ageLimitCategoryList);
        return returnMap;
    }

    @Override
    public Map<String, Object> queryHospitals(User user, ChartsAreaQuery chartsAreaQuery) throws Exception {
        Map<String,Object> returnMap = new HashMap<>();
        Map<String,Object> paramMap = getParamMap(user, chartsAreaQuery);
        ChartsBaseDataView allAssets = chartsForAreaAllocationDao.queryAllAssets(paramMap);
        List<ChartsBaseDataView> list;
        //redis未宕机且只有年份和设备类型筛选的情况
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)){
            String key = getAreaModuleKey("allocation",user,"hospital",chartsAreaQuery);
            //查询redis中是否有该缓存
            list = getListValue(redisTemplate,key);
            if(list == null){
                //医院数据
                list = chartsForAreaAllocationDao.queryHospitals(paramMap);
                new Thread(new RedisListStoreThread(redisTemplate,key,list)).start();
            }
        }else{
            list = chartsForAreaAllocationDao.queryHospitals(paramMap);
        }

        //设置平均指方便气泡图四个象限设置
        Double avgPrice = 0.0;
        Double avgCounts = 0.00;
        if(allAssets != null && list != null && list.size() != 0){
            avgPrice = allAssets.getCurPrice()/list.size()*1.0;
            avgCounts = allAssets.getCurCounts()/list.size()*1.0;
        }
        returnMap.put("avgPrice",avgPrice);
        returnMap.put("avgCounts",avgCounts);
        returnMap.put("list",list);
        return returnMap;
    }

    @Override
    public Map<String,Object> queryDeviceTypes (User user, ChartsAreaQuery chartsAreaQuery) throws Exception {
        Map<String,Object> returnMap = new HashMap<>();
        Map<String,Object> paramMap = getParamMap(user, chartsAreaQuery);
        ChartsBaseDataView allAssets = getAllAssets(user,paramMap,chartsAreaQuery);
        List<ChartsBaseDataView> list;
        //redis未宕机且只有年份和设备类型筛选的情况
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)){
            //查询redis中是否有该缓存
            String key = getAreaModuleKey("allocation",user,"type",chartsAreaQuery);
            list = getListValue(redisTemplate,key);
            if(list == null){
                //设备类型数据
                list = chartsForAreaAllocationDao.querySecondDeviceTypes(paramMap);
                new Thread(new RedisListStoreThread(redisTemplate,key,list)).start();
            }
        }else{
            list = chartsForAreaAllocationDao.querySecondDeviceTypes(paramMap);
        }

        //设置平均指方便气泡图四个象限设置
        Double avgPrice = 0.0;
        Double avgCounts = 0.00;
        if(allAssets != null && list != null && list.size() != 0){
            //二级68分类数量之和
            int size = list.stream().map((x)->x.getList() == null ? 1 : x.getList().size()).reduce(0,Integer::sum);
            avgPrice = allAssets.getCurPrice()/size*1.0;
            avgCounts = allAssets.getCurCounts()/size*1.0;
        }
        returnMap.put("avgPrice",avgPrice);
        returnMap.put("avgCounts",avgCounts);
        returnMap.put("list",list);
        return returnMap;
    }

    @Override
    public Map<String, Object> queryDeviceModels(User user, ChartsAreaQuery chartsAreaQuery) throws Exception {
        Map<String,Object> returnMap = new HashMap<>();
        Map<String,Object> paramMap = getParamMap(user, chartsAreaQuery);
        ChartsBaseDataView allAssets = getAllAssets(user,paramMap,chartsAreaQuery);
        List<ChartsBaseDataView> list;
        //redis未宕机且只有年份和设备类型筛选的情况
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)){
            //查询redis中是否有该缓存
            String key = getAreaModuleKey("allocation",user,"model",chartsAreaQuery);
            list = getListValue(redisTemplate,key);
            if(list == null){
                //设备型号数据
                list = chartsForAreaAllocationDao.queryDeviceModels(paramMap);
                new Thread(new RedisListStoreThread(redisTemplate,key,list)).start();
            }
        }else{
            list = chartsForAreaAllocationDao.queryDeviceModels(paramMap);
        }

        //去除型号为空和空字符串的情况
        List<ChartsBaseDataView> filterList = list.stream().filter(x->x !=null && !StringUtil.isEmpty(x.getId())).collect(Collectors.toList());

        //设置平均指方便气泡图四个象限设置
        Double avgPrice = 0.0;
        Double avgCounts = 0.00;
        if(allAssets != null && filterList != null && filterList.size() != 0){
            avgPrice = allAssets.getCurPrice()/filterList.size()*1.0;
            avgCounts = allAssets.getCurCounts()/filterList.size()*1.0;
        }
        returnMap.put("avgPrice",avgPrice);
        returnMap.put("avgCounts",avgCounts);
        returnMap.put("list",filterList);
        return returnMap;
    }

    @Override
    public  Map<String,Object> queryDeviceBrands(User user, ChartsAreaQuery chartsAreaQuery) throws Exception {
        Map<String,Object> returnMap = new HashMap<>();
        Map<String,Object> paramMap = getParamMap(user, chartsAreaQuery);
        List<ChartsBaseDataView> list ;
        //redis未宕机且只有年份和设备类型筛选的情况
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)){
            //查询redis中是否有该缓存
            String key = getAreaModuleKey("allocation",user,"brand",chartsAreaQuery);
            list = getListValue(redisTemplate,key);
            if(list == null){
                //设备详情数据
                list = chartsForAreaAllocationDao.queryDeviceBrands(paramMap);
                new Thread(new RedisListStoreThread(redisTemplate,key,list)).start();
            }
        }else{
            list = chartsForAreaAllocationDao.queryDeviceBrands(paramMap);
        }
        returnMap.put("list",list);
        return returnMap;
    }

    @Override
    public  Map<String,Object> queryDeviceInfoByModelName(User user, ChartsAreaQuery chartsAreaQuery) throws Exception {
        Map<String,Object> returnMap = new HashMap<>();
        Map<String,Object> paramMap = getParamMap(user, chartsAreaQuery);
        List<ChartsAssetsBaseDataView> list;
        //redis未宕机且只有年份和设备类型筛选的情况
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)){
            //查询redis中是否有该缓存
            String key = getAreaModuleKey("allocation",user,"assets",chartsAreaQuery);
            list = getListValue(redisTemplate,key);
            if(list == null){
                //设备详情数据
                list = chartsForAreaAllocationDao.queryDeviceInfoByModelName(paramMap);
                new Thread(new RedisListStoreThread(redisTemplate,key,list)).start();
            }
        }else{
            list = chartsForAreaAllocationDao.queryDeviceInfoByModelName(paramMap);
        }
        returnMap.put("list",list);
        return returnMap;
    }

    @Override
    public List<Map<String,Object>> queryYearTrend(User user, ChartsAreaQuery chartsAreaQuery) throws Exception {
        Map<String,Object> paramMap = getParamMap(user, chartsAreaQuery);
        Calendar calendar = Calendar.getInstance();
        Integer year = calendar.get(Calendar.YEAR);
        //拼接当前年份前三年的id,名称
        for(int i=2;i>=0;i--){
            paramMap.put("asId"+i,year-i-1);
            paramMap.put("asName"+i,year-i-1);
            paramMap.put("year"+i,(year-i)+"-1-1");
        }
        //拼接当前年份的id,name
        paramMap.put("asId",year);
        paramMap.put("asName",year);

        List<Map<String,Object>> list;
        //redis未宕机且只有年份和设备类型筛选的情况
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)){
            //查询redis中是否有该缓存
            String key = getAreaModuleKey("allocation",user,"yearTrend",chartsAreaQuery);
            list = getListValue(redisTemplate,key);
            if(list == null) {
                //设备详情数据
                list = chartsForAreaAllocationDao.queryYearTrend(paramMap);
                new Thread(new RedisListStoreThread(redisTemplate, key, list)).start();
            }
        }else{
            list = chartsForAreaAllocationDao.queryYearTrend(paramMap);
        }
        return list;
    }

    @Override
    public Map<String, Object> queryNewlyOrScrapAssetsInfo(User user, ChartsAreaQuery chartsAreaQuery) throws Exception {
        Map<String,Object> returnMap = new HashMap<>();
        Map<String,Object> paramMap = getParamMap(user, chartsAreaQuery);
        List<ChartsAssetsBaseDataView> list = chartsForAreaAllocationDao.queryNewlyOrScrapAssetsInfo(paramMap);
        returnMap.put("list",list);
        return returnMap;
    }

    /**
     * @Author: 杨青桦
     * @Description:  获取总资产情况共用方法
     * @Date: 2018/5/30 14:46
     * @param user
     * @param chartsAreaQuery
     * @return
     * @throws Exception
     */
    private ChartsBaseDataView getAllAssets(User user,Map paramMap,ChartsAreaQuery chartsAreaQuery) throws Exception{
        ChartsBaseDataView allAssets;
        if(RedisUtil.isOn && isQueryNullOrOnlyType(chartsAreaQuery)) {
            //医院key
            String key = getAreaModuleKey("allocation",user,"allAssets",chartsAreaQuery);
            allAssets = RedisUtil.getValue(redisTemplate, key);
            if(allAssets == null){
                allAssets = chartsForAreaAllocationDao.queryAllAssets(paramMap);
                new Thread(new RedisValueStoreThread(redisTemplate, key, allAssets)).start();
            }
        }else{
            allAssets = chartsForAreaAllocationDao.queryAllAssets(paramMap);
        }
        return allAssets;
    }


}
